﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using iNet.Tasks;

namespace iNet.Media
{
	/// <summary>
	/// 媒體編碼工作的基底類別。
	/// </summary>
	public abstract class MediaEncodeTask : MediaTask
	{
		#region 欄位
		MediaStorage _Destination;
		int _DestinationLockTimeout = 5000;
		IMediaFormat _EncodingFormat;
		IMetadata _EncodingMetadata;
		MediaEncodeRequests _MediaEncodeRequests;
		#endregion
		#region 建構子
		/// <summary>
		/// 初始化新的 MediaEncodeTask 執行個體。
		/// </summary>
		/// <param name="encodingFormat">媒體編碼格式。</param>
		/// <exception cref="ArgumentNullException">encodingFormat 為 Null (Visual Basic 為 Nothing)。</exception>
		protected MediaEncodeTask(IMediaFormat encodingFormat)
		{
			if (encodingFormat == null)
				throw new ArgumentNullException("encodingFormat");
			_EncodingFormat = encodingFormat;
		}
		/// <summary>
		/// 初始化新的 MediaEncodeTask 執行個體。
		/// </summary>
		/// <param name="encodingFormat">媒體編碼格式。</param>
		/// <param name="destination">儲存編碼結果的媒體儲存。</param>
		/// <param name="request">編碼請求。</param>
		/// <exception cref="ArgumentNullException">encodingFormat 為 Null (Visual Basic 為 Nothing)。</exception>
		protected MediaEncodeTask(IMediaFormat encodingFormat, MediaStorage destination, MediaEncodeRequests request)
			: this(encodingFormat)
		{
			_Destination = destination;
			_MediaEncodeRequests = request;
		}
		#endregion
		#region CreateCompatibleMetadata
		/// <summary>
		/// 建立與此媒體格式相容且可編輯的中繼資料。
		/// </summary>
		/// <param name="template">現有的中繼資料。</param>
		/// <returns>與此媒體格式相容的中繼資料。</returns>
		public virtual IMetadata CreateCompatibleMetadata(IMetadata template)
		{
			if (template != null && template.IsReadOnly)
				return (template.Clone() as IMetadata);
			return (template != null ? template : new GenericMetadata());
		}
		#endregion
		#region Destination
		/// <summary>
		/// 取得或設定儲存編碼結果的媒體儲存。
		/// </summary>
		public MediaStorage Destination
		{
			get
			{
				return _Destination;
			}
			set
			{
				this.SetInitializingParameter<MediaStorage>(ref _Destination, value);
			}
		}
		#endregion
		#region DestinationLockTimeout
		/// <summary>
		/// 取得或設定鎖定媒體儲存的最長嘗試時間，單位為毫秒。零表示失敗後立即返回，預設值為 5000。
		/// </summary>
		public int DestinationLockTimeout
		{
			get
			{
				return _DestinationLockTimeout;
			}
			set
			{
				if (value < 0)
					throw new ArgumentOutOfRangeException();
				this.SetInitializingParameter<int>(ref _DestinationLockTimeout, value);
			}
		}
		#endregion
		#region Encode
		/// <summary>
		/// 將媒體編碼。
		/// </summary>
		/// <param name="version">工作版本。</param>
		/// <param name="destination">儲存編碼結果的媒體儲存。</param>
		/// <param name="mediaEncodeReqs">編碼請求。</param>
		/// <returns>True 表示編碼完成，False 表示編碼失敗。</returns>
		protected abstract bool Encode(TaskVersion version, MediaStorage destination, MediaEncodeRequests mediaEncodeReqs);
		#endregion
		#region EncodingFormat
		/// <summary>
		/// 取得媒體的編碼格式。
		/// </summary>
		public IMediaFormat EncodingFormat
		{
			get
			{
				return _EncodingFormat;
			}
		}
		#endregion
		#region EncodingMetadata
		/// <summary>
		/// 取得或設定編碼的中繼資料，Null (Visual Basic 為 Nothing) 表示直接使用媒體本身的中繼資料。
		/// </summary>
		public IMetadata EncodingMetadata
		{
			get
			{
				return _EncodingMetadata;
			}
			set
			{
				this.SetInitializingParameter<IMetadata>(ref _EncodingMetadata, value);
			}
		}
		#endregion
		#region Execute
		protected override bool Execute(TaskVersion version)
		{
			//確認參數
			if (_Destination == null)
				throw new InvalidOperationException();

			//重設進度
			this.ReportProgress(version, null);

			//編碼媒體
			return this.Encode(version, _Destination, _MediaEncodeRequests);
		}
		#endregion
		#region MediaEncodeRequests
		/// <summary>
		/// 取得或設定媒體的編碼請求組合。
		/// </summary>
		public MediaEncodeRequests MediaEncodeRequests
		{
			get
			{
				return _MediaEncodeRequests;
			}
			set
			{
				this.SetInitializingParameter<MediaEncodeRequests>(ref _MediaEncodeRequests, value);
			}
		}
		#endregion
		#region SupportedMediaEncodeRequests
		/// <summary>
		/// 取得支援的編碼請求組合。
		/// </summary>
		public virtual MediaEncodeRequests SupportedMediaEncodeRequests
		{
			get
			{
				return MediaEncodeRequests.EncodeMetadata;
			}
		}
        #endregion
	}
	#region MediaEncodeRequests
	/// <summary>
	/// 表示媒體編碼的請求組合。
	/// </summary>
	[Flags]
	public enum MediaEncodeRequests
	{
		/// <summary>
		/// 將中繼資料編碼。
		/// </summary>
		EncodeMetadata = 0x1,
	}
	#endregion
}
